﻿//using ConsoleApp1;
using CSharp;
using CSharp._18bangTableAdapters;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
//using System.Data.SqlClient;
using System.IO;
using System.Linq;
using Microsoft.Data.SqlClient;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Transactions;
using static ConsoleApp1.Program;
using static CSharp._18bang;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
using Microsoft.EntityFrameworkCore.Storage;


//using _17bang;
namespace CSharp
{
    //public interface ILearn
    //{
    //    void Golesson();
    //    void Practice();
    //    double Score { get; set; }


    //}
    //public interface IPlay
    //{
    //    void Practice();
    //}

    ////[OnlineAttribute(5, Version = 3)]//给OnlineAttribute对象的Version属性赋值
    //public struct Bed
    //{

    //}
    //public class Student : Person
    //{
    //    public IList<Major> Majors { get; set; }
    //    public static object[] students =
    //    {
    //            new Student(){ Name = "lw"},
    //            new Student(){ Name = "zl"},
    //            new Student(){ Name = "zdh"},
    //            new Student(){ Name = "lgy"},
    //    };
    //    public IEnumerator GetEnumerator()
    //    {
    //        return new Enumerator(this);//this传的是整个Student函数
    //    }
    //    struct Enumerator : IEnumerator//类中类
    //    {
    //        private object _current;
    //        private object[] _localstudents;
    //        private int _index;

    //        public object Current
    //        {
    //            get { return _current; }
    //        }

    //        public Enumerator(Student student)
    //        {
    //            _localstudents = Student.students;//传入object[] students数组
    //            _index = 0;
    //            _current = _localstudents[_index];
    //        }
    //        public bool MoveNext()//MoveNext里面调用Current
    //        {
    //            if (_index >= _localstudents.Length)
    //            {
    //                return false;
    //            }
    //            _current = _localstudents[_index];
    //            _index++;
    //            return true;
    //        }

    //        public void Reset()
    //        {
    //            throw new NotImplementedException();
    //        }
    //    }
    //    public override void Eat()
    //    {
    //        Console.WriteLine("去学生家吃饭");

    //    }


    //}
    //public class Teacher : Person
    //{
    //    public int Age { get; set; }
    //    public IList<Major> Major { get; set; }
    //    public Teacher()
    //    {
    //    }
    //    public override void Eat()
    //    {
    //        Console.WriteLine("去老师家吃饭");
    //    }
    //}
    //public class Major : Person
    //{
    //    public int Age { get; set; }
    //    public IList<Student> Students { get; set; }
    //    public decimal Difficulty { get; internal set; }
    //    public string TeacherName { get; set; }
    //}

    //public class Person
    //{
    //    public double Score { get; set; }
    //    public int Age { set; get; }
    //    public string Name { set; get; }

    //    public void Grow(Person person)
    //    {
    //        person.Age++;
    //    }

    //    public Person()
    //    {
    //    }
    //    public virtual void Eat()
    //    {

    //    }

    //    public string ToString(string format, IFormatProvider formatProvider)
    //    {
    //        return "I implement IFormattable";
    //    }
    //}
    class Program
    {
        static void Main(string[] args)
        {
            SQLDbContext context = new SQLDbContext();

            #region Create DB
            ////关系更新
            ////分别取出学生和老师，把取出的学生赋值给老师的集合
            //IList<Student> students = context.Students.Where(s => s.Id < 3).ToList();
            //Teacher t2 = context.Find<Teacher>(2);
            //t2.Students.Clear(); //先把结果集清空，先删除原本的学生，
            //                     //再添加查找出的学生，可以更新学生和老师关系
            //t2.Students = students;
            //context.SaveChanges();

            ////将学生和老师的关系删除，但不删除他们本身  多对多的双向引用
            //Student lzb = context.Find<Student>(1);
            //context.Entry(lzb).Collection(s => s.Teachers).Load();
            ////要先使用两个entity，才能触发其加载机制
            //lzb.Teachers = null; //LazyLoad模式，不算调用，就不会触发机制

            ////多对多的双向引用  删除学生的其中一个老师
            //Teacher fg = context.Find<Teacher>(1);
            //Student gty = context.Find<Student>(2);
            //fg.Students.Remove(gty);
            //context.SaveChanges();

            ////一对多的引用关系 删除一个教室中的其中一个学生的关系
            //Classroom c1 = context.Find<Classroom>(1);
            //c1.Students.RemoveAt(0);
            //context.SaveChanges();


            ////级联删除 删除第一个房间里的学生
            //Classroom c1 = context.Classrooms.Where(c => c.Id == 1).SingleOrDefault();
            //context.Entry(c1).Collection(s => s.Students).Load();
            //context.Remove(c1);


            ////删除多对多表中的Id=2的老师的学生  
            //Teacher t2 = context.Teachers
            //    .Where(t => t.Id == 2)
            //    .Include(t => t.Students)
            //    .SingleOrDefault();
            //context.Remove(t2);
            //context.SaveChanges();

            ////删除一对一一个学生的床，床为主表，自定义级联删除
            //Bed lw = context.Find<Bed>(1);
            //context.Entry(lw).Reference(s => s.Student).Load();
            //context.Remove(lw);
            //context.SaveChanges();



            //查出不同教室里面所有的所有学生的姓名  解决Lazy模式出现的1+N问题
            //foreach (var room in context.Classrooms.Include(c => c.Students)
            //    .ToList()) //ToList立即执行
            //{
            //    Console.WriteLine(room.Name);
            //    foreach (var student in room.Students)
            //    {
            //        Console.WriteLine($"      {student.Name}");
            //    }
            //}

            //显式加载 Entry 先取得一个entity，再调用collection等方法获取其集合对象
            //Classroom c1 = context.Classrooms.Where(c => c.Id == 1).SingleOrDefault();
            //context.Entry<Classroom>(c1)
            //    .Collection(c => c.Students)
            //        .Query().Where(s => s.Name == "l")
            //    .Load();

            //foreach (var item in c1.Students)
            //{
            //    Console.WriteLine(item.Name);
            //}

            ////预先加载 Include
            //Classroom c2 = context.Classrooms
            //    .Include(c => c.Students.AsQueryable())
            //    .Where(c => c.Id == 2).SingleOrDefault();
            //foreach (var item in c2.Students
            //    .Where(s => s.Name.Contains("l")))
            //{
            //    Console.WriteLine(item.Name);
            //}

            //context.Add(
            //    new Student
            //    {
            //        Name = "刘伟",
            //        Bed = new Bed
            //        {
            //            Location = "大通铺-床底"
            //        }
            //    }); //一对一关联

            //context.Add(
            //    new Teacher
            //    {
            //        Name = "大飞",
            //        Students = new List<Student>
            //        {
            //            new Student{Name = "lw"},
            //            new Student{Name = "zl"}
            //        }
            //    }); //一对多关联  一个老师有多个学生 学生表插入TeacherId，所以先Insert Teacher
            #endregion

            //实现增删改，在savechange()执行中开启事务
            //多个Savechange（）开启多个事务 
            using (IDbContextTransaction transaction = context.Database.BeginTransaction())
            {
                try
                {
                    Student lzb = context.Find<Student>(1);
                    lzb.Name = "李志博";
                    context.SaveChanges();

                    Teacher fg = context.Find<Teacher>(1);
                    fg.Salary = -100;
                    context.SaveChanges();

                    transaction.Commit();
                }
                catch (Exception)
                {
                    transaction.Rollback();
                    throw;
                }
            }
            


            //API生成表Persons
            //var db = context.Database;
            //db.EnsureDeleted();
            //db.EnsureCreated();


            //Student lw = new Student { Name = "lw" };
            //Student lzb = new Student { Name = "lzb" };
            //Student lgy = new Student { Name = "lgy" };
            //Student gty = new Student { Name = "gty" };

            //Classroom csharp = new Classroom { Name = "csharp" };
            //Classroom sql = new Classroom { Name = "sql" };

            //csharp.Students = new List<Student> { lw, lzb, gty };
            //sql.Students = new List<Student> { lgy, lw };

            //Teacher fg = new Teacher { Name = "fg" };
            //Teacher xy = new Teacher { Name = "xy" };

            //fg.Students = new List<Student> { lw, lzb, gty };
            //xy.Students = new List<Student> { lgy, lw };

            //Bed closure = new Bed { Location = "bibao" };
            //Bed factory = new Bed { Location = "gongcang" };

            //lw.Bed = closure;
            //lzb.Bed = factory;

            //context.AddRange(fg, xy);
            //context.AddRange(csharp, sql);
            //context.SaveChanges();

            //include()会让EF通过JOIN的方法，一次性的从数据库取出关联的信息
            //Student s1 = context.Students
            //    .Where(s => s.Id == 1)  //找到Id为1的学生
            //    .Include(s => s.Bed)  //包含当前entity的关联对象（包含Student的Bed对象）
            //    .Single();
            //Console.WriteLine(s1.BedId); //可以拿到  作为外键存在
            //Console.WriteLine(s1.Bed.Location); //在EF中，关联对象不会被默认加载

            //预先加载是Jion两张表进行查询，显示加载是分为两张表进行查询的

            //预先加载:关联的数据会随着entity加载同时加载
            //通过老师得到学生的床位号等信息
            //Teacher fg = context.Teachers
            //    .Where(t => t.Name == "fg") //找到名为fg的老师
            //        .Include(t => t.Students) //包含当前entity（Teacher）的关联对象（Students）
            //            .ThenInclude(s => s.Bed) //再包含Students的Bed
            //    .Single();
            //Console.WriteLine(fg.Students[0].Bed.Location);


            //显式加载:先取到一个entity之后，再利用方法entry获取该entity在DbContext中的追踪信息，
            //然后调用其Collection/Reference方法，获取其集合/关联对象，最后用Load进行加载。
            //Teacher xy = context.Teachers
            //    .Where(t => t.Name == "xy")
            //    .SingleOrDefault(); //先取得一个Entity，不会加载出关联对象
            ////之后要用到关联对象，用Entry方法实现
            //context.Entry(xy) //Entry获取该Entity在DbContext中的追踪信息
            //    .Collection(f => f.Students)  //获取该entity的单个的关联或集合对象，最后再调用
            //    .Load(); //Load进行加载


            //Student lw = context.Students
            //    .Where(s => s.Name == "lw")
            //    .SingleOrDefault();
            //context.Entry(lw)
            ////.Property("EnrollDate").CurrentValue = DateTime.Now;
            //.Reference(l => l.Bed)
            //.Load();
            //context.SaveChanges();
            //Console.WriteLine(lw.Bed.Location);

            //延迟加载（代理模式）：引入dll，配置使用proxy，在entity的所有的关联对象加上virtual
            //EF自动新建生成子类对象BedProxy，是Bed的子类，proxy对象只有主键（Id）被赋值，其他属性值为默认值（null、0、false等）
            //它里面有LazyLoader属性，负责在使用时自动连接数据库，获取相关数据，予以加载

            //Student lw = context.Students.Where(s => s.Name == "lw").SingleOrDefault();

            //Console.WriteLine(lw.Bed.Location); //在查询时自动加载
            //Console.WriteLine(lw.Classroom.Students.Count);

            //context.AddRange(fg, xy); //多对多关联
            //单向的一对一
            //Bed bed = new Bed();
            ////1对1，因为一个Bed只有一个Student,如果给Bed赋一样的值，就会产生替代
            //Student zl = new Student { Name = "zl", Bed = bed };
            //Student lzb = new Student { Name = "lzb"};

            //context.Add(zl);
            //context.Add(lzb);

            //context.SaveChanges();
















            //在表中插入数据
            //context.AddRange(
            //    new Person { Name = "女娲" },
            //    new Student { Name = "小鱼",Score = 97.6},
            //    new Teacher { Name = "飞哥" ,Salary = 5432}
            //    );
            //context.SaveChanges();

            //Linq方法查找数据
            //查询的是Person，不会调用Discriminator列
            //Person nv = context.Persons
            //    .Where(p => p.Name == "女娲").SingleOrDefault();

            //查询的是Teacher，调用Discriminator列
            //Teacher fg = context.Teachers
            //    .Where(t => t.Name == "飞").FirstOrDefault();

            //存储返回的是Person，但实际上是Students表，依然会调用Discriminator
            //Person xy = context.Persons
            //    .Where(s => s.Name == "小鱼").SingleOrDefault();
            //Student s = (Student)xy;
            //Console.WriteLine(s.Score);

            //int maxId = 100;
            ////string name = "小童";
            //IQueryable<Student> query =
            //    context.Students
            //    //.FromSqlInterpolated($"SELECT * FROM Students WHERE Id > {maxId}");
            //    .FromSqlRaw("SELECT * FROM Students WHERE Id > @Id",
            //    new SqlParameter("Id", maxId));
            //.AsEnumerable()

            //query = query.Where(q => q.Id > 3000);

            //IList<Student> students = query.AsNoTracking().ToList();


            //Student student = context.Students.Find(3003);   //查

            //Student student = new Student { Name = "小灰" };
            //context.Attach<Student>(student); //先Attach，再修改 Unchanged  
            //student.IsFemale = false; //改

            //context.Students.Update(student); //主键Id不赋值，会执行Insert  Added

            //context.Students.Remove(student); //删
            //Student student = new Student
            //{
            //    //Id = 2,
            //    Name = "小勋",
            //};
            //context.Students.Add(student); //增

            //context.Add(student);
            //context.Add<Student>(student);
            //context.SaveChanges(); //将代码保存到数据库

            //强类型DataSet
            //_18bang bang = new _18bang();
            //StudentRow student = bang.Student.FindById(0);
            //student.Name = "";

            //取出表Student的全部数据
            //GetData() 生成一个新的DataTable,由数据库StudentDataTable的值填充
            //Fill() 将数据填充到DataTable中
            //StudentTableAdapter adapter1 = new StudentTableAdapter();
            //StudentDataTable student = adapter1.GetData();

            //在可视化界面新增一个删除的方法
            //adapter1.DeleteById(18);  //数据库Id为18的一行被删除  底层实现ExecuteNonQuery


            //student.Where(s => s.Id == 11).SingleOrDefault().Delete();  //删除数据库的数据

            //adapter1.Update(student);
            //删除的错误写法
            //student.Rows.Remove(student.Rows[0]);  //不会删除数据库的数据
            //删除的正确写法
            //student.Rows[0].Delete();



            //string queryString = "SELECT * FROM Teacher";
            //string connectionString = @"Data Source=(localdb)\MSSQLLocalDB;
            //                        Initial Catalog=18bang;Integrated Security=True";

            //SqlConnection connection = new SqlConnection(connectionString);

            //SqlDataAdapter adapter = new SqlDataAdapter(queryString, connection);

            //DataSet dsTeacher = new DataSet();
            //adapter.Fill(dsTeacher); //"非连接式查询"，一旦Fill（），就会关闭

            //dsTeacher.Tables[0].Rows[0]["Name"] = "Mino";


            ////修改老师的名称
            //SqlCommand updateCmd = new SqlCommand("UPDATE Teacher SET [Name] = @name WHERE [Id] = @Id", connection);//所以SQLCommand还需要连接

            ////将parameter加入SQLCommand
            //SqlParameter pName = new SqlParameter("@name", SqlDbType.NVarChar);
            //pName.SourceColumn = "Name";  //指定参数数据来源列
            //updateCmd.Parameters.Add(pName);

            //SqlParameter pId = new SqlParameter("@Id", SqlDbType.Int);
            //pId.SourceColumn = "Id";
            //updateCmd.Parameters.Add(pId);

            ////将SQLcommand加入adapter上的UpdateCommand（SQLDataAdapter才可以）
            //adapter.UpdateCommand = updateCmd;
            ////IDataAdapter需要强制转换
            //((SqlDataAdapter)adapter).InsertCommand = updateCmd;

            //adapter.Update(dsTeacher);



            //DataTable dtTeacher = new DataTable("Teacher");
            //dtTeacher.Columns.Add("Id", typeof(int));
            //dtTeacher.Columns.Add("Name", typeof(string));
            //dtTeacher.Rows.Add(1, "小新");
            //dtTeacher.Rows.Add(2, "小白");
            //dtTeacher.Rows.Add(3, "小葵");

            //DataSet ds17bang = new DataSet("17bang");
            //ds17bang.Tables.Add(dtTeacher);

            //ds17bang.Tables.Add(new DataTable("Major"));

            //Console.WriteLine(ds17bang.Tables["Teacher"].Rows[0]["Name"]);

            ////从DataTable中取出给定条件（比如Name = "小葵"）的某行的Id（Row）
            //foreach (DataTable table in ds17bang.Tables)
            //{
            //    foreach (DataRow row1 in table.Rows)
            //    {
            //        if (row["Name"].ToString() == "小葵")
            //        {
            //            Console.WriteLine(row["Id"]);
            //            break;
            //        }
            //    }
            //}
            ////Linq    .AsEnumerable()绝对不能省略
            //object Id = ds17bang.Tables["Teacher"].AsEnumerable()
            //    .Where(t => t["Name"].ToString() == "小白")
            //    .SingleOrDefault()?["Id"];
            //Console.WriteLine(Id);

            //DataRow xx = ds17bang.Tables["Teacher"].AsEnumerable()      
            //   .Where(r => r["Name"].ToString() == "小新")
            //   .SingleOrDefault();
            //Console.WriteLine(xx["Id"]);

            //DBHelper helper = new DBHelper();
            //IDataParameter pId = new SqlParameter("@Id", 10);

            //helper.Delete($"DELETE ShortStudent WHERE Id = @Id;", pId);

            //helper.Update(new SqlCommand
            //{
            //    CommandText = $"UPDATE ShortStudent SET [Name] = N'小葵' where Id = @Id",
            //    Parameters = { pId }
            //});

            //int[] ids = new int[] { 12, 16 };
            ////根据ids的Id，生成commands的数组   有多少id就有多少个commands
            //IDbCommand[] commands = new IDbCommand[ids.Length];
            //for (int i = 0; i < ids.Length; i++)
            //{
            //    commands[i] = new SqlCommand
            //    {
            //        CommandText = $"DELETE ShortStudent WHERE Id = @id "
            //    };
            //    //public SqlParameter(string parameterName, object value);
            //    commands[i].Parameters.Add(new SqlParameter("@id", ids[i]));
            //}
            //调用函数需要commands，所以在外面创造commands
            //helper.DeleteRange(commands);

            //string name = Console.ReadLine();
            //string password = Console.ReadLine();

            //using (TransactionScope scope = new TransactionScope() )
            //{
            //    scope.Complete();
            //    //在一定时间内未提交，会自动释放回滚该事务
            //}

            //string connectionString =    
            //    @"Data Source=(localdb)\MSSQLLocalDB;
            //      Initial Catalog=18bang;
            //      Integrated Security=True";

            //using (IDbConnection connection = helper.GetNewconnection())
            //{
            //    connection.Open();

            //    using (IDbTransaction transaction = connection.BeginTransaction())   //用connection开启事务
            //    {
            //        try
            //        {
            //            IDbCommand command = new SqlCommand();
            //            command.Connection = connection;
            //            //绑定command和transaction
            //            command.Transaction = transaction;

            //            //能够正常执行
            //            command.CommandText = "UPDATE Student SET Age -= 1";
            //            command.ExecuteNonQuery();

            //            //会违反Age>0的约束
            //            command.CommandText = "UPDATE Student SET Age += 5";
            //            command.ExecuteNonQuery();

            //            transaction.Commit();
            //        }
            //        catch (Exception)
            //        {
            //            transaction.Rollback();
            //            //注意不能对异常“不予处理”，直接吞了
            //            throw;
            //        }
            //    }


            //在SQL创建存储过程，在ADO.NET传入参数，调用存储过程
            //connection.Open();
            //IDbCommand command = new SqlCommand();

            //command.CommandType = CommandType.StoredProcedure;  //指定存储过程的类型
            //command.Connection = connection;
            //command.CommandText = "GetExcellentStudents";  //创建的存储过程的名称

            //IDataParameter pScore = new SqlParameter("@score", 80);  //通过IDataParameter传入存储过程的参数（参数名字，赋值）
            //command.Parameters.Add(pScore); //将输入参数加到command上

            //IDataParameter pCount = new SqlParameter("@count", SqlDbType.Int) //此时Parameter没有给输出参数赋值，指明输出参数的类型
            //{
            //    Direction = ParameterDirection.Output //指明@count的方向是OUTPUT类型的参数
            //};
            //command.Parameters.Add(pCount); //将输出参数加到command上
            //command.ExecuteScalar();
            //Console.WriteLine(pCount.Value);  //执行完成后拿到参数的值

            //String dbPassword = command.ExecuteScalar()? .ToString();
            //if (dbPassword == null)
            //{
            //    Console.WriteLine("*用户名不存在*");
            //    return; //截断式编程
            //}

            //if (dbPassword != password)
            //{
            //    Console.WriteLine("*用户名或密码错误*");
            //    return; 
            //}

            //command.CommandText = "INSERT ShortStudent VALUES(N'小雨') ";
            //int rowsAffected = command.ExecuteNonQuery();
            //Console.WriteLine(rowsAffected);

        }


        //IDbConnection connection = new SqlConnection(connectionString);
        //IDbCommand command = new SqlCommand();
        //command.Connection = connection;
        //command.CommandText = "SELECT * FROM ShortStudent";

        //try
        //{
        //    connection.Open();
        //    IDataReader reader = command.ExecuteReader();  //执行这一步没有数据！ 将所有SELECT查询的数据取出来放在客服端（ADO.NET）的网络缓冲区缓，
        //                                                   //reader不是容器，这时不会将结果集放在里面


        //    while (reader.Read()) //每一次Read（）不会再次连接数据库进行查询，而是从网络缓冲区进行查询
        //    {
        //        for (int i = 0; i < reader.FieldCount; i++)
        //        {
        //            Console.Write(reader[i] + "  ");
        //        } 
        //        Console.WriteLine();
        //    }

        //}
        //catch (Exception)
        //{

        //    throw;
        //}
        //finally
        //{
        //    connection.Close();
        //    connection.Dispose();
        //    connection = null;
        //}

    }
}

//不使用string自带的Join()方法，定义一个mimicJoin()方法，能将若干字符串character 用指定的分隔符separator连接起来，
// 比如：mimicJoin("-","a","b","c","d")，其运行结果为：a-b-c-d   StringBuilder
//public static string minicJoin(string separator, string[] character)
//{
//    StringBuilder sb = new StringBuilder();
//    for (int i = 0; i < character.Length; i++)
//    {
//        sb.Append(character[i]);
//        if (i == character.Length - 1)
//        {
//            break;
//        }
//        sb.Append(separator);
//    }
//    return sb.ToString();
//}
////实现GetCount(string container, string target)方法，可以统计出container中有多少个target 
////比如一串字符串(1234576587654327768)里面有多少个关键字(76)
////找到第一个关键字，在循环剩下的字符找第二个关键字，第三个....四...
//public static void GetCount(string container, string target)
//{

//    //public int IndexOf(String value, int startIndex);
//    //返回指定字符串从该实例中指定字符位置开始搜索第一次出现的索引，索引从0开始
//    int index = 0;
//    int count = 0;
//    for (int i = 0; i < container.Length; i++)
//    {
//        if ((index = container.IndexOf(target, index)) != -1)
//        {
//            count++;
//            //Console.WriteLine($"第{count}次；索引是{index}");
//            Console.WriteLine($"关键字出现的总次数：{count}");
//            index = index + target.Length;
//        }
//        else
//        {
//            break;
//        }
//    }
//}
////2.给定任意一个年份，就能按周排列显示每周的起始日期
///// <summary>
///// 获得某一年的第一个星期一
///// </summary>
///// <param name="year">指定的年份</param>
///// <returns>第一个星期一的日期
//public static void ShowWeeks(DateTime start/*,bool includeLastyear,bool includeNextyear*/)
//{
//    start = GetFirstMonday(2019);
//    int i = 1;
//    int currentyear = start.Year;
//    while (start.Year == currentyear)
//    {
//        Console.WriteLine($"第{i}周：,{start.ToString("yyyy年MM月dd日")}-{start.AddDays(6).ToString("yyyy年MM月dd日")}");
//        start = start.AddDays(7);
//        i++;
//    }
//}
//public static DateTime GetFirstMonday(int year)
//{
//    ///从该年1月1日起，开始循环，直到找到第一个星期一
//    ///判断是不是星期一
//    ///如果不是，再加一天
//    ///否则，返回当天
//    ///找到第一个星期一的日期day
//    ///星期一加6天显示一个周期
//    DateTime day = new DateTime(year, 1, 1);
//    while (day.DayOfWeek != DayOfWeek.Monday)
//    {
//        day.AddDays(1);
//    }
//    return day;
//}
////确保用户（User）的密码（Password）：
////长度不低于6
////必须由大小写英语单词、数字和特殊符号（~!@#$%^&*()_+）组成
//public string Password
//{
//    set { _password = value; }
//}
//private string _password;
//public static bool PasswordRule(string _password)
//{
//    string number = "1234567890";
//    string character = "~!@#$%^&*()_+";
//    string letter = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";
//    if (_password.Length <= 6)
//    {
//        Console.WriteLine("密码长度不能低于6");
//        return false;
//    }
//    else
//    {
//        for (int i = 0; i < number.Length; i++)
//        {
//            if (_password.Contains(number[i]))
//            {
//                continue;
//            }
//            break;
//        }
//        for (int i = 0; i < character.Length; i++)
//        {
//            if (_password.Contains(character[i]))
//            {
//                continue;
//            }
//            break;
//        }
//        for (int i = 0; i < letter.Length; i++)
//        {
//            if (_password.Contains(letter[i]))
//            {
//                continue;
//            }
//            break;
//        }
//        return true;
//    }
//}
//public static Person GetStudent(string Name)
//{
//    if (true)
//    {
//        return new Person();
//    }
//    else
//    {
//        return null;
//    }
//}

////根据需求选择返回类型
////使用IEnumerable，只想进行foreach迭代循环，不需要下标、数量等
////也可以使用ICollection，使用添加、删除、清除、数量统计等
//static IEnumerable<int> GetSingleDigitNumbers()
//{
//    yield return 0;
//    yield return 1;
//    yield return 2;
//    yield return 3;
//    yield return 4;

//}
//static void Exam(IEnumerable<int> students)
//{
//    foreach (var item in students)
//    {
//        Console.WriteLine(item);
//    }
//}
//static Func<int> AICaculate()
//{
//    //Console.WriteLine("I'm AI caculator, let me try:");
//    //opt(a, b);
//    int a = 100, b = 50;//通常方法调用后，a、b的值会出栈消失。
//    //但是Lambda表达式使得方法延长生命周期和作用域，方法结束后还没有被销毁
//    //return a+b;//委托不能直接返回a+b
//    return () => a + b;//Lambda表达式只有返回值要加空括号（）
//}

//// Linq的实质是foreach，
//// 所以，数据源（source date）要求必须是IEnumerable或它的子类
////内部就会用foreach方法迭代实现
//static IEnumerable<T> filterByAge<T>(IEnumerable<T> student,
//    Func<T, bool> predicate)
//{
//    //IList<T> result = new List<T>();
//    foreach (var item in student)
//    {
//        if (predicate(item))
//        {
//            yield return item;
//            //返回的是一个匿名的（系统生成的）IEnumerable<int>实例，实例中按顺序存储上述数据
//            //result.Add(item);
//        }
//    }
//    //return result;
//}


//static int getAge(int old)
//{
//    Thread.Sleep(5000);//5000
//    return new Random().Next(100);
//}
//static void grow()
//{
//    for (int i = 0; i < 10; i++)
//    {
//        Thread.Sleep(100);//1000
//        Console.WriteLine("growing..." + i);
//    }
//}

////await后面开始异步！
////同时进行awatable（getRandom（））中的内容和调用方法处Process（）后面的内容
////当awatable中的内容执行完毕，暂停方法调用处内容，继续执行await后面的代码
////异步方法调用完毕，继续执行方法调用处内容

////返回void Process()方法最终不会回到主线程
////返回Task<T> 最终会回到主线程 Process().Result;
//public static async /*Task<int>*/ void Process()////方法的声明：返回的是Task<int>
//{
//    Console.WriteLine("    in Process() before await...");

//    int result = await getRandom();
//    Console.WriteLine("getRandom(): " + result);
//    Console.WriteLine("    in Process() after await...");

//    //return result;//方法体内，返回的是int
//}
//public static Task<int> getRandom()//getRandom()只能返回Task<int>方法，
//                                   //而我们想得到的是Random随机值，要通过调用Result得到
//{
//    //没有任务，主线程
//    Console.WriteLine($"in getRandom() Task.CurrentId: {Task.CurrentId}");//没有
//    Console.WriteLine($"in getRandom() Thread.CurrentThread.ManagedThreadId: " +
//        $"{Thread.CurrentThread.ManagedThreadId}");//主线程1
//    return Task<int>.Run(() =>
//    {
//        //新任务，新线程
//        Console.WriteLine($"     in getRandom() Task.CurrentId: {Task.CurrentId}");//1
//        Console.WriteLine($"     in getRandT-SQLom() Thread.CurrentThread.ManagedThreadId: " +
//            $"{Thread.CurrentThread.ManagedThreadId}");//新线程4
//        Thread.Sleep(100);
//        return new Random().Next();
//    });
//}
//static void Main(string[] args)
//{
//    //参考一起帮的登录页面，绘制一个验证码图片，存放到当前项目中。验证码应包含：

//    //随机字符串
//    //混淆用的各色像素点
//    //混淆用的直线（或曲线）

//    //现有一个txt文件，里面存放了若干email地址，使用分号（;）或者换行进行了分隔。请删除其中重复的email地址，并按每30个email一行（行内用; 分隔）重新组织

//    //将生成验证码的代码拆分成若干个方法，并为其添加异常机制，要求能够：

//    //    显式的抛出一个自定义异常
//    //    捕获并包裹一个被抛出的异常，记入日志文件，然后再次抛出
//    //    根据不同的异常，给用户相应的友好的异常提示
//    //    使用using释放文件资源


//    //在D盘存入一个文件夹，里面有一个记录的文件，
//    //可以先检查这个文件夹是否存在，创造一个新的文件夹，创造文件，再写入内容

//    string directory = @"D:\源栈\源栈四期\C#语法\3-高级进阶";
//    string filename = @"log.txt";
//    Console.WriteLine(Directory.Exists(directory));

//    string path = Path.Combine(directory, "fg");
//    Directory.CreateDirectory(path);

//    string fullFilename = Path.Combine(path, filename);
//    File.Create(fullFilename);//创建文件
//    File.WriteAllText(fullFilename, "源栈欢迎您"); //创建文件并写入内容


//    //File.OpenRead() ：打开文件读
//    FileStream stream = File.OpenRead(fullFilename);
//    byte[] array = new byte[100];
//    while (stream.Read(array, 0, 100) > 0) //读缓冲区为了减少磁盘读数据的次数
//    {
//        //array
//    }
//    //Console.WriteLine();

//    //File.OpenWrite(path)：打开文件然后写 
//    FileStream fileStream = File.OpenWrite(filename);
//    fileStream.Write(new byte[4] { 12, 45, 7, 92 }, 0, 5);//不会直接写入磁盘，先写入缓冲区buffer
//    fileStream.Flush();//将缓冲区内容写入文件


//    //必须重开一个strem流
//    FileStream stream = null;
//    try
//    {
//        stream = File.OpenRead(fullFilename);
//        byte[] array = new byte[100];
//        stream.Read(array, 0, array.Length);
//        stream.Flush();
//        Console.WriteLine(Encoding.UTF8.GetString(array));
//    }
//    catch (Exception)
//    {
//        throw;
//    }
//    finally
//    {
//        stream.Dispose();//调用Dispose()释放文件资源，让其他“人”也可以操作该文件 
//    }

//    using (FileStream stream = File.OpenRead(fullFilename))
//    //在using块结束时调用其Dispose()方法
//    {
//        byte[] array = new byte[100];
//        stream.Read(array, 0, array.Length);
//        stream.Flush();
//        Console.WriteLine(Encoding.UTF8.GetString(array));
//    }

//for (int i = 0; i < 5; i++)
//{
//    Console.WriteLine(); Parallel.Invoke(
//       () =>
//       {
//           Console.WriteLine(i + $":task-{Task.CurrentId} in thread-{Thread.CurrentThread.ManagedThreadId}");
//           Console.WriteLine($"task-{Task.CurrentId} begin in thread-{Thread.CurrentThread.ManagedThreadId}");
//           Console.WriteLine($"task-{Task.CurrentId} in thread-{Thread.CurrentThread.ManagedThreadId}");
//           Console.WriteLine($"task-{Task.CurrentId} end in thread-{Thread.CurrentThread.ManagedThreadId}");
//       },
//       () =>
//       {
//           Console.WriteLine(i + $":task-{Task.CurrentId} in thread-{Thread.CurrentThread.ManagedThreadId}");
//           Console.WriteLine($"task-{Task.CurrentId} in begin in thread-{Thread.CurrentThread.ManagedThreadId}");
//           Console.WriteLine($"task-{Task.CurrentId} in thread-{Thread.CurrentThread.ManagedThreadId}");
//           Console.WriteLine($"task-{Task.CurrentId} in end in thread-{Thread.CurrentThread.ManagedThreadId}");
//       }
//   );
//}


//Console.WriteLine($"before process...Task.CurrentId: {Task.CurrentId}");//没有
//Console.WriteLine($"before process...Thread.CurrentThread.ManagedThreadId: " +
//    $"{Thread.CurrentThread.ManagedThreadId}");//主线程1
//Console.WriteLine("before process...");

//Process();
//Console.WriteLine("after process...");

//for (int i = 0; i < 10; i++)
//{
//    Console.WriteLine($"after process...Task.CurrentId: {Task.CurrentId}");//没有
//    Console.WriteLine($"after process...Thread.CurrentThread.ManagedThreadId: " +
//        $"{Thread.CurrentThread.ManagedThreadId}");//主线程1

//    Thread.Sleep(10);
//    Console.WriteLine("after process , i =" + i);
//}
//Console.Read();
//同步输出：
//before process...
//    in Process() before await...
//getRandom(): 1734256051
//    in Process() after await...
//after process...
//after process, i = 0
//after process, i = 1
//after process, i = 2
//after process, i = 3
//after process, i = 4
//after process, i = 5
//after process, i = 6
//after process, i = 7
//after process, i = 8
//after process, i = 9
//异步输出：
//before process...
//     in Process() before await...
//after process...
//after process, i = 0
//after process, i = 1
//after process, i = 2
//after process, i = 3
//after process, i = 4
//after process, i = 5
//after process, i = 6
//getRandom(): 840339101
//    in Process() after await...
//after process, i = 7
//after process, i = 8
//after process, i = 9





//同步,按顺序实现
//6000
//DateTime begin = DateTime.Now;
//grow();
//Console.WriteLine(getAge());

//异步,grow在当前线程，getAge异步
//5000 执行getAge时，同时开线程执行grow，时间重叠

////如果Task需要的方法有参数，怎么传递？
//Task taskGetAge = new Task(() => getAge(78));
//taskGetAge.Start();
//grow();
//taskGetAge.RunSynchronously();//等同于同步
//taskGetAge.Wait();
//Console.WriteLine((DateTime.Now - begin).TotalMilliseconds);

//for (int i = 0; i < 20; i++)
//{
//    Console.WriteLine($"i(out) : {i}");
//    Task task = new Task(
//() =>
//{
//    Console.WriteLine($"i(in) : {i}");
//    Console.WriteLine($"I'm in Task{Task.CurrentId}...");
//    Console.WriteLine($"CurrentThread-Id : {Thread.CurrentThread.ManagedThreadId}");
//    Console.WriteLine($"IsBackground-Id : {Thread.CurrentThread.IsBackground}");
//    Console.WriteLine($"IsThreadPoolThread-Id : {Thread.CurrentThread.IsThreadPoolThread}");
//});
//    task.Start();
//    Thread.Sleep(1000);
//}

//for (int i = 0; i < 20; i++)
//{
//    Task<int> age = new Task<int>
//        (
//        () =>
//        {
//            Console.WriteLine($"i(in) : {i}");
//            Console.WriteLine($"I'm in Task{Task.CurrentId}...");
//            Console.WriteLine($"CurrentThread-Id : {Thread.CurrentThread.ManagedThreadId}");

//            return 24 + i;
//        }
//        );
//    age.Start();

//    //很复杂的操作

//    Console.WriteLine(age.Result);
//}


//Console.WriteLine("Out of Task...");
////多线程  可以new一个
//Thread thread = new Thread(Process);//新创建的线程运行Process方法
//Console.WriteLine(thread.ManagedThreadId);//托管线程Id

//Console.WriteLine(thread.Priority);//优先级
//Console.WriteLine(thread.IsThreadPoolThread);//是否在线程池
//thread.Start(); //两个线程“同时”执行
//Console.WriteLine(thread.ThreadState);//线程的状态，放在Start前面是UNStarted，其后是Running


//Console.WriteLine();
//Console.WriteLine();
//Console.WriteLine();

////单线程 当前线程为主线程
//Thread current = Thread.CurrentThread;

//Console.WriteLine(Thread.GetDomain().FriendlyName);//当前线程所在的进程
//Console.WriteLine(current.ManagedThreadId);//托管线程Id
////项目经理要求写的，以后客户优化好加钱
//Thread.Sleep(3000); //当前线程进入休眠状态1s

//Console.WriteLine(current.Priority);//优先级
//Console.WriteLine(current.ThreadState);//线程的状态
//Console.WriteLine(current.IsThreadPoolThread);//是否在线程池






//for (int i = 0; i < 5; i++)
//{
//    ScoreGrade? grade = null; //使grade的作用域一致，可以在try...catch外面输出
//    try
//    {
//        //int input = Convert.ToInt32(Console.ReadLine());
//        ///*ScoreGrade */grade = new Score(input).Transfor();
//        ////Console.WriteLine(grade); 输出写在try中不推荐

//        //异常会带来较大的资源开销（性能损耗）
//        //避免异常被抛出，从性能角度考虑，使代码更有健壮性
//        if (int.TryParse(Console.ReadLine(), out int input))
//        {
//            grade = new Score(input).Transfor();
//        }
//        if (input < 0 || input > 100)
//        {
//            Console.WriteLine("输入的值不在0到100的范围内");

//        }
//    }
//    catch (FormatException)//try里面的代码会抛出的异常可以通过F12查看
//    {
//        Console.WriteLine("输入的值无法转换成int类型");//提示信息：终端用户的友好提示
//    }
//    catch (ArgumentOutOfRangeException)
//    {
//        Console.WriteLine("输入的值不在0到100的范围内");
//    }
//    catch (Exception e)//无法处理的异常继续往上抛
//    {
//        Console.WriteLine($"发现一个错误：{e.ToString()}");//e.ToString 数据重写，输出Exception的全部信息
//        //错误来自Exception(类)，后面可传变量
//        //记日志log，以便查阅
//        throw new Exception("输入的值无法转换成int类型", e);//单个throw，将异常信息原封不动抛出
//        //封装成新的异常抛出,将当前异常作为innerException写入
//    }
//    finally
//    {
//        //清理工作，最后一定会执行finally的程序(return、throw都会执行finally)
//        Console.WriteLine(grade);

//    }
//    Console.WriteLine(new Student().ToString());//没有override的ToString输出类的全名
//}



//Teacher和Major是多对一的关系
//Student和Major是多对多的关系
//    Teacher fg = new Teacher { Age = 24, Name = "大飞哥" };
//    Teacher fish = new Teacher { Age = 19, Name = "小鱼" };
//    Teacher dfg = new Teacher { Age = 40, Name = "大飞哥", };
//    IEnumerable<Teacher> teachers = new List<Teacher> { fg, fish, dfg };

//    Major SQL = new Major { Name = "SQL", TeacherName = "大飞哥", Age = 24 };
//    Major Javascript = new Major { Name = "Javascript", TeacherName = "大飞哥", Age = 40 };
//    Major UI = new Major { Name = "UI", TeacherName = "小鱼", Age = 19 };
//    Major csharp = new Major { Name = "C#", TeacherName = "大飞哥", Age = 24 };
//    IEnumerable<Major> majors = new List<Major> { csharp, SQL, Javascript, UI };

//    IList<Student> students1 = new List<Student>
//    {
//        new Student{Score = 98,Name = "屿",Majors = new List<Major>{csharp,SQL } },
//        new Student{Score = 86, Name = "行人", Majors=new List<Major>{Javascript, csharp, SQL} },
//        new Student{Score = 78, Name = "王平", Majors=new List<Major>{csharp}},
//        new Student{Score = 89, Name = "王枫", Majors=new List<Major>{Javascript, csharp, SQL,UI}},
//        new Student{Score = 98, Name = "蒋宜蒙", Majors=new List<Major>{Javascript, csharp}},
//    };



//    //查出每个学生的老师的姓名 student和major之间
//    //SelectMany:选出集合中元素的集合
//    //student集合中有major集合，先将major取出来，再进行加工
//    var result5 = students1.SelectMany(s => s.Majors, //指示取出students里的所有Major
//        (s, m) => new //组合student和major
//        {
//            s,
//            m.TeacherName,
//            m.Age,
//            m.Name
//        });
//    foreach (var item in result5)
//    {
//        Console.WriteLine($"{item.s.Name}的{item.Name}老师是: {item.TeacherName }({item.Age})");
//    }


//    //找到老师姓名和年龄都一一对应的课程
//    //将Major和teacher进行join(姓名年龄相等)
//    var result2 = majors.Join(teachers,
//        m => new { Name = m.TeacherName, m.Age },
//        t => new { t.Name, t.Age },
////判断两个匿名函数相等，需要属性的顺序数量名称都相同
//(m, t) => new
//{
//    tName = t.Name,
//    mName = m.Name
//});

//    //每个老师教了几门课
//    //通过老师的名字和年龄对课程分组，但是要输出年龄和名字两个属性，推荐用匿名对象
//    var result = majors.GroupBy(m => new { m.TeacherName, m.Age });
//    //foreach (var item in result)
//    //{
//    //    Console.WriteLine($"{item.Key.TeacherName} ({item.Key.Age}){item.Count()}");
//    //}

//    //不直接输出，而是将GroupBy分组的结果进行整理，装入新的集合，用投影实现
//    //r 代表result里面的每一个元素
//    var stat = result.Select(r => new
//    {
//        r.Key.TeacherName,
//        r.Key.Age,
//        Count = r.Count()
//    });
//    foreach (var item in stat)
//    {
//        Console.WriteLine($"{item.TeacherName} : ({item.Age}) : {item.Count}");
//    }


//查找成绩高于60分的同学
//var result1 = from s in students1
//             where s.Score > 60
//             select s;
////var result = students1.Where(s => s.Score > 60);
////当Linq查询表达式比较简单时，用Linq方法显得简洁很多
////Linq表达式和Linq方法可以混用

//IList<IGrouping<Teacher,Student>> lstStudent = result.ToList();
////在满足成绩的同学里找到姓王的学生
//if (true) //根据用户输入,继续查找
//{
//    result = from r in lstStudent/*result.ToList()*/  //ToList()，之后只会在result.ToList()集合中执行，不会执行Add()
//             where r.Name.StartsWith("王")
//             select r;
//    result = result.Where(r => r.Name.StartsWith("王"));
//}
//students1.Add(new Student { Score = 89, Name = "王枫-2", Majors = new List<Major> { Javascript, csharp, SQL, UI } });

////在满足以上的条件中查找选修三门课程以上的学生
//if (true)
//{
//    result = from r in result
//             where r.Majors.Count() > 3
//             select r;
//    result = result.Where(r => r.Majors.Count() > 3);
//}
//foreach (var item in result)
//{
//    Console.WriteLine($"{item.Name} : {item.Score} ({item.Majors.Count()})"); //王枫 : 89 (4)
//                                                                             //王枫 - 2 : 89 (4)
//}

////将所有学生学了哪几门课程依次输出
//var result4 = from s in students1 //将students的所有元素放入s
//              let sm = s.Majors //students的课程放入sm
//              from m in sm //从sm中找出major
//              select new { nameStudent = s.Name, nameMajor = m.Name };
//foreach (var item in result)
//{
//    //Console.WriteLine(item.nameStudent + ": " + item.nameMajor);//屿: SQL
//    //行人: Javascript
//}

//找到老师姓名和年龄都一一对应的课程
//多个条件连接的情况
//var ms = from t in teachers
//         join m in majors
//         on new { t.Age, t.Name } equals new { m.Age, Name = m.TeacherName }
//         //判断两个匿名函数相等，需要属性的顺序数量名称都相同
//         select new { teacher = t.Name, major = m.Name, age = t.Age };
////用投影实现输出多个元素
//foreach (var item in ms)
//{
//    Console.WriteLine(item.teacher + $"{item.age} : " + item.major);//大飞哥24 : C#
//                                                                    // 大飞哥24: SQL
//                                                                    //小鱼19 : UI
//                                                                    //大飞哥40 : Javascript
//}
//var result3 = from m in majors //join连接
//      from t in teachers
//on m.TeacherID equals t.ID
//where t.Name == "小鱼"
//select new//用投影实现输出多个元素
//              {
//                  t.ID,
//                  teacherName = t.Name,
//                  majorName = m.Name
//              };
//foreach (var item in result3)
//{
//    Console.WriteLine($"{item.ID}-{item.teacherName}-{item.majorName}");
//}

//select通过new一个匿名类
//可以将多个属性组合，比如将学生的姓名和成绩组合
//var excellent = from s in students1
//                select new
//                //匿名类
//                {
//                    s.Name,
//                    s.Score
//                };

//foreach (var item in excellent)
//{
//    Console.WriteLine(item.Name + ":" + item.Score);
//}

////每个老师上了多少门课
////通过Group得到的结果集再用into进行处理，
//var stat1 = from m in majors
//            group m by m.TeacherName //到此为止，得到分组结果集(按老师给课程分组) 
//           into gm //into类似于命名，将之前的结果集命名为：gm
//                   //接下来对分组结果集再运算（统计）
//            select new /*KeyValuePair<Teacher, int>*/ //利用投影
//            {
//                gm.Key,
//                Count = gm.Count()
//            };
////Count()是统计有几门课

////将IEum转换成各种集合类型
////var lstStat = stat.ToList();
////此时的stat还是IEnumerable类型，IstSTat是list类型的
////var lstStat = stat.ToDictionary(s => s.Key, s => s.Count);
//// 1 of 4 :重载 (extension):扩展方法
//// Dictionary<TKey,'a>:TKey是返回值
//// IEnumerable<'a>.ToDictionary<'a,TKey>:IEnumerable是类型,ToDictionary是方法的名字
////(Func<'a,Tkey>keySelector):方法的参数
//foreach (var item in stat1)
//{
//    Console.WriteLine(item.Key + ":" + item.Count);//输出： 大飞哥:3 小鱼: 1
//}

//IEqualityComparer<TKey> comparer  .Net类库自动比较传入的键是否重复相等，若你的判断与.Net不同，可以自行编写IEquality接口进行判断


//IEnumerable<IGrouping<Teacher, Major>> result =
//    //通过分组后的IEum集合里面，每个元素又是一个集合，集合中有属性Key
//    from n in majors//按老师给课程分组
//    group n by n.Teacher
//             ;
//foreach (IGrouping<Teacher,Major> item in result)
////result [0]key 大飞哥 -->item [0]csharp  [1]SQL  [2]JavaScript
////result [1]key 小鱼 -->item [0]UI
//{
//    Console.WriteLine(item.Key.Name);
//    //老师的名字 第一次循环输出：大飞哥 第二次循环输出：小鱼
//    foreach (var major in item)//item可实现foreach迭代，因为IGroup实现了IEumerable
//    {
//        Console.WriteLine(major.Name);
//        //第一次循环输出：C# SQL JAvaScript 第二次循环输出：UI
//    }
//    Console.WriteLine(item.Count());
//    Console.WriteLine(item.Sum(m => m.Difficulty));
//    Console.WriteLine(item.Average(m => m.Difficulty));
//}


//foreach (var item in student)
//{
//    Console.WriteLine(item.Age);
//}


//Func<Student, Person> func = s => new Person();
//Func委托代表引用的方法，
//要求输入的参数是Student类型，返回结果是Person类型 
//Func<Student, Person> func2 = s = new Student();
//由out定义的参数类型，可以用子类替代
//由in定义的参数类型，可以用父类替代
//Func<Student, Person> func1 = GetTeacher;

//Func<int> func = AICaculate();//AICaculate运行的结果赋值给委托变量func 
//func();//委托可以像方法一样调用

//new List<int>().Any<int>();
//Student student = new Student();
////student.Learn("李志博");
//Console.WriteLine(student.Name);

//IEnumerable<int> numbers = GetSingleDigitNumbers();
//Exam(numbers);//竖着输出 0 1 2 3 4

////Exam(GetSingleDigitNumbers());

//numbers.Average();
//Enumerable.Average(参数);
//静态类里面的静态方法，本应由类调用，但是可以用被作为参数的实例调用，被称为扩展方法

//Program.GetFirstMonday(start);
//ShowWeeks(GetFirstMonday(2019));


//List<int> age = new List<int> { 5, 10, 12, 18, 24 };
//age.Add(27);
//age.Remove(18);

//Dictionary<string, double> scores = new Dictionary<string, double>
//{
//    {"小红",98 },
//    {"小明",92 },
//    {"小新",61 }
//};
//Console.WriteLine(scores["小红"]);//只能通过键取值，可以值相同，不能键相同

//Exam(new List<Student>());
//Exam(new Queue<Student>());


//IList<Student> students = new List<Student>//习惯写IList大鞋装小脚，继承
//{
//    new Student(){ Name = "lw"},
//    new Student(){ Name = "zl"},
//    new Student(){ Name = "zdh"},
//    new Student(){ Name = "lgy"},

//};


//上述foreach实质上等于：

//IEnumerator<Student> enumerator = students.GetEnumerator();
////集合有GetEnumerator()方法，通过这个方法返回 IEnumerator<Student>这个对象，对象里面有MoveNext()
//while (enumerator.MoveNext())
//{
//    var item = enumerator.Current;
//    Console.WriteLine(item);
//}

//Dictionary<string, Student> students = new Dictionary<string, Student>
//{
//    {"lw",new Student() },
//    {"zl",new Student() },
//    {"lzb",new Student() },
//    {"lgy",new Student() }
//};

//            IList<Student> students = new List<Student>
//            {
//                 new Student{Age = 14},
//                 new Student{Age = 28},
//                 new Student{Age = 20},
//            };
//            students.Any(s => s.Age > 20);//s是参数，Lambda表达式表示条件
//                                          //Lambda表达式的判断条件直接传递给扩展方法的MyAny方法，可直接使用参数调用方法
//                                          //声明MyAny方法，和Any一样可以实现方法


//            DLinkNode<int> node1 = new DLinkNode<int> { Value = 1 };
//            DLinkNode<int> node2 = new DLinkNode<int> { Value = 2 };
//            DLinkNode<int> node3 = new DLinkNode<int> { Value = 3 };
//            DLinkNode<int> node4 = new DLinkNode<int> { Value = 4 };
//            DLinkNode<int> node5 = new DLinkNode<int> { Value = 5 };

//            node1.AddAfter(node2);
//            node2.AddAfter(node3);
//            node3.AddAfter(node4);
//            node4.AddAfter(node5);

//            foreach (var item in node1)
//            {
//                Console.WriteLine(item.Value);
//            }
//            //var maxValue = node5.MyMax();
//            //Console.WriteLine(maxValue);
//        }
//    }
//}
//调用扩展方法Max()：能够返回之前双向链表中存贮着最大值的节点
//public static int Max<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector);
//public static class ExtensionMethod
//{
//    public static T MyMax<T>(this DLinkNode<T> source)
//    {
//        return source.Value;
//    }
//}

//public static class IExtensionMethod
//{
//    public static bool MyAny<T>(this IList<T> source, Func<T, bool> predicate)
//    //泛型方法，委托Func<int T,out result> predicate（条件）
//    //score [0] [1] [2] {CSharp.Student}
//    {
//        foreach (T item in source)//var是List的元素类型,item {CSharp.Student} Age 14、28、20
//        {
//            if (predicate(item))
//            {
//                return true;
//            }
//        }
//        return false;
//    }
//}
//public delegate TResult myFunc<in T1, out TResult>(T1 t1);




















